package com.tjf.lib_utils;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
import android.graphics.text.LineBreaker;
import android.os.Build;
import android.text.InputFilter;
import android.text.TextPaint;
import android.text.method.ArrowKeyMovementMethod;
import android.text.method.MovementMethod;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.ActionMode;
import android.view.Gravity;

import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;

public class EditableTextView extends AppCompatTextView {

    // 常量定义，提高代码可读性
    private static final int DEFAULT_BOX_COLOR = Color.parseColor("#42BBBBBB");
    private static final float DEFAULT_CURSOR_WIDTH_DP = 1;
    private static final float DEFAULT_CURSOR_HEIGHT_DP = 20;
    private static final int DEFAULT_INPUT_BOX_NUM = 4;
    private static final float DEFAULT_BOX_RADIUS_DP = 12;
    private static final float DEFAULT_BOX_SPACE_DP = 12;
    private static final long CURSOR_BLINK_DELAY = 500;
    private static final long DELAY_BEFORE_HANDLE_FADES_OUT = 4000;

    private RectF inputRect = new RectF();
    // 边框颜色
    private int boxColor = DEFAULT_BOX_COLOR;
    // 光标是否可见
    private boolean isCursorVisible = false;
    // 光标
    private Drawable textCursorDrawable;
    // 光标宽度
    private float cursorWidth;
    // 光标高度
    private float cursorHeight;
    // 光标闪烁控制
    private boolean isShowCursor;
    // 字符数量控制
    private int inputBoxNum = DEFAULT_INPUT_BOX_NUM;
    // 间距
    private int mBoxSpace;
    // box radius
    private float boxRadius;

    private InputFilter[] inputFilters;

    // 避免 paint.getFontMetrics 内部频繁创建对象
    private final Paint.FontMetrics fm = new Paint.FontMetrics();

    private final Runnable invalidateCursor = new Runnable() {
        @Override
        public void run() {
            invalidate();
        }
    };

    public EditableTextView(Context context) {
        this(context, null);
    }

    public EditableTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public EditableTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        // 初始化光标相关属性
        cursorWidth = dp2px(DEFAULT_CURSOR_WIDTH_DP);
        cursorHeight = dp2px(DEFAULT_CURSOR_HEIGHT_DP);
        mBoxSpace = (int) dp2px(DEFAULT_BOX_SPACE_DP);
        boxRadius = dp2px(DEFAULT_BOX_RADIUS_DP);

        inputFilters = new InputFilter[]{
                new InputFilter.LengthFilter(inputBoxNum)
        };

        Drawable cursorDrawable = getTextCursorDrawable();
        if (cursorDrawable == null) {
            cursorDrawable = new PaintDrawable(Color.MAGENTA);
            setTextCursorDrawable(cursorDrawable);
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            setBreakStrategy(LineBreaker.BREAK_STRATEGY_SIMPLE);
        }
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        // 支持聚焦
        super.setFocusable(true);
        // 支持触屏模式聚焦
        super.setFocusableInTouchMode(true);
        // 可点击
        super.setClickable(true);
        super.setGravity(Gravity.CENTER_VERTICAL);
        super.setMaxLines(1);
        super.setSingleLine();
        super.setFilters(inputFilters);
        // 禁止复制、剪切
        super.setLongClickable(false);
        // 禁止选中
        super.setTextIsSelectable(false);
        super.setOnClickListener(v -> setCursorVisible(true));
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            super.setPointerIcon(null);
        }
        super.setOnLongClickListener(v -> true); // 抑制长按出现弹窗的问题
        // 禁用 ActonMode 弹窗
        super.setCustomSelectionActionModeCallback(null);
    }

    @Override
    public ActionMode startActionMode(ActionMode.Callback callback) {
        return null;
    }

    @Override
    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
        return null;
    }

    @Override
    public boolean hasSelection() {
        return false;
    }

    @Override
    public boolean showContextMenu() {
        return false;
    }

    @Override
    public boolean showContextMenu(float x, float y) {
        return false;
    }

    public void setBoxSpace(int mBoxSpace) {
        this.mBoxSpace = mBoxSpace;
        invalidate();
    }

    public void setInputBoxNum(int inputBoxNum) {
        if (inputBoxNum <= 0) return;
        this.inputBoxNum = inputBoxNum;
        this.inputFilters[0] = new InputFilter.LengthFilter(inputBoxNum);
        super.setFilters(inputFilters);
        invalidate();
    }

    @Override
    public void setClickable(boolean clickable) {
        // 不允许外部修改点击属性
    }

    @Override
    public void setLines(int lines) {
        // 不允许外部修改行数
    }

    @Override
    protected boolean getDefaultEditable() {
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        TextPaint paint = getPaint();

        // 设置默认的 strokeWidth
        float strokeWidth = paint.getStrokeWidth();
        if (strokeWidth == 0) {
            paint.setStrokeWidth(dp2px(1));
            strokeWidth = paint.getStrokeWidth();
        }
        paint.setTextSize(getTextSize());

        // 计算每个输入框的宽度和高度
        float boxWidth = (getWidth() - strokeWidth * 2f - (inputBoxNum - 1) * mBoxSpace) / inputBoxNum;
        float boxHeight = getHeight() - strokeWidth * 2f;
        int saveCount = canvas.save();

        Paint.Style originalStyle = paint.getStyle();
        Paint.Align originalAlign = paint.getTextAlign();
        paint.setTextAlign(Paint.Align.CENTER);

        String text = getText().toString();
        int length = text.length();

        int originalColor = paint.getColor();

        for (int i = 0; i < inputBoxNum; i++) {
            // 计算输入框的位置
            inputRect.set(i * (boxWidth + mBoxSpace) + strokeWidth,
                    strokeWidth,
                    strokeWidth + i * (boxWidth + mBoxSpace) + boxWidth,
                    strokeWidth + boxHeight);

            // 绘制边框
            paint.setStyle(Paint.Style.FILL);
            paint.setColor(boxColor);
            canvas.drawRoundRect(inputRect, boxRadius, boxRadius, paint);

            // 设置当前文字颜色
            int currentTextColor = getCurrentTextColor();
            paint.setColor(currentTextColor);
            paint.setStyle(Paint.Style.FILL);

            if (length > i) {
                // 绘制文字
                String ch = String.valueOf(text.charAt(i));
                int baseLineY = (int) (inputRect.centerY() + getTextPaintBaseline(paint));
                canvas.drawText(ch, inputRect.centerX(), baseLineY, paint);
            }

            // 绘制光标
            if (i == length && isCursorVisible && length < inputBoxNum) {
                Drawable cursorDrawable = getTextCursorDrawable();
                if (cursorDrawable != null) {
                    if (!isShowCursor) {
                        cursorDrawable.setBounds((int) (inputRect.centerX() - cursorWidth / 2f),
                                (int) ((inputRect.height() - cursorHeight) / 2f),
                                (int) (inputRect.centerX() + cursorWidth / 2f),
                                (int) ((inputRect.height() - cursorHeight) / 2f + cursorHeight));
                        cursorDrawable.draw(canvas);
                        isShowCursor = true;
                    } else {
                        isShowCursor = false;
                    }
                    removeCallbacks(invalidateCursor);
                    postDelayed(invalidateCursor, CURSOR_BLINK_DELAY);
                }
            }
        }

        // 恢复画笔的原始属性
        paint.setColor(originalColor);
        paint.setStyle(originalStyle);
        paint.setTextAlign(originalAlign);

        canvas.restoreToCount(saveCount);
    }

    /**
     * 计算基线到中线的距离
     */
    public float getTextPaintBaseline(Paint p) {
        p.getFontMetrics(fm);
        return (fm.descent - fm.ascent) / 2 - fm.descent;
    }

    @Override
    public boolean getFreezesText() {
        return true;
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        super.setText(text, BufferType.EDITABLE);
    }

    @Override
    protected MovementMethod getDefaultMovementMethod() {
        return ArrowKeyMovementMethod.getInstance();
    }

    @Override
    public boolean isCursorVisible() {
        return isCursorVisible;
    }

    @Override
    public void setTextCursorDrawable(@Nullable Drawable textCursorDrawable) {
        this.textCursorDrawable = textCursorDrawable;
        invalidate();
    }

    @Nullable
    @Override
    public Drawable getTextCursorDrawable() {
        return textCursorDrawable;
    }

    @Override
    public void setCursorVisible(boolean cursorVisible) {
        isCursorVisible = cursorVisible;
        invalidate();
    }

    public float dp2px(float dp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
    }

    public void setBoxRadius(float boxRadius) {
        this.boxRadius = boxRadius;
        invalidate();
    }

    public void setBoxColor(int boxColor) {
        this.boxColor = boxColor;
        invalidate();
    }

    public void setCursorHeight(float cursorHeight) {
        this.cursorHeight = cursorHeight;
        invalidate();
    }

    public void setCursorWidth(float cursorWidth) {
        this.cursorWidth = cursorWidth;
        invalidate();
    }

    @Override
    public boolean postDelayed(Runnable action, long delayMillis) {
        if (delayMillis == DELAY_BEFORE_HANDLE_FADES_OUT
                && action.getClass().getName().startsWith("android.widget.Editor$InsertionHandleView$")) {
            delayMillis = 0;
        }
        return super.postDelayed(action, delayMillis);
    }
}